package cn.hf.mychat.constanst;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author Roskin
 *
 */
public class BeanX {
	/**
	 * contains only alphanumerics, including both capitals and smalls.
	 */
	public static final char[] DICTIONARY_62 =
	            new char[]{'0','1','2','3','4','5','6','7','8','9',
	            		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
	            		'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
	protected char[] dictionary;
	
	public BeanX() {
		this.dictionary = DICTIONARY_62;
	}
	
	public BeanX(char[] dictionary) {
		this.dictionary = dictionary;
	}
	/**
	 * encodes the given string into the base of the dictionary provided in the constructor.
	 * @param value
	 * @return
	 */
	public String encode(BigInteger value) {
		List<Character> result = new ArrayList<>();
		BigInteger base = BigInteger.valueOf(dictionary.length);
		int exponent = 1;
	    BigInteger remaining = value;
	    while(true) {
	    	BigInteger a = base.pow(exponent);	//16^1 = 16
	    	BigInteger b = remaining.mod(a);	//119 % 16 = 7 | 112 % 256 = 112
	    	BigInteger c = base.pow(exponent-1);
	    	BigInteger d = b.divide(c);
	    	//if d > dictionary.length, we have a problem. but BigInteger does not have
            //a greater than method :-(  hope for the best. theoretically, d is always
            //an index of the dictionary!
	    	result.add(dictionary[d.intValue()]);
	    	remaining = remaining.subtract(b);	 //119 - 7 = 112 | 112 - 112 = 0
	    	if(remaining.equals(BigInteger.ZERO)) {
	    		break;
	    	}
	    	exponent++;
	    }
	    
	  //need to reverse it, since the start of the list contains the least significant values
	  StringBuffer  sb = new StringBuffer();
	  for(int i = result.size()-1; i >= 0; i--){
          sb.append(result.get(i));
      }
      return sb.toString();
	}
	/**
	 * decodes the given string from the base of the dictionary provided in the constructor.
	 * @param str
	 * @return
	 */
	public BigInteger decode(String str) {
		//reverse it, its already reversed!
        char[] chars = new char[str.length()];
        str.getChars(0, str.length(), chars, 0);
        
        char[] new_chars = new char[str.length()];
        int i = new_chars.length -1;
        for(char c:chars) {
        	new_chars[i--] = c;
        }
        
        //for efficiency, make a map
        Map<Character, BigInteger> dictMap = new HashMap<>();
        int j=0;
        for(char c:dictionary) {
        	dictMap.put(c, BigInteger.valueOf(j++));
        }
        BigInteger bi = BigInteger.ZERO;	
        BigInteger base = BigInteger.valueOf(dictionary.length);
        int exponent = 1;
        for(char c:new_chars) {
        	BigInteger a = dictMap.get(c);
        	BigInteger b = base.pow(exponent).multiply(a);
        	bi = bi.add(b);
        	exponent++;
        }
        
		return bi;
	}
	
	
	


}
